package com.xcexample.electronicclasscard.main

import android.content.Context
import android.content.pm.PackageManager
import android.hardware.Camera
import android.os.Bundle
import android.os.Environment
import android.os.Handler
import android.os.Looper
import android.text.TextUtils
import android.util.DisplayMetrics
import android.util.Log
import android.view.LayoutInflater
import android.view.SurfaceHolder
import android.view.View
import android.view.ViewGroup
import android.view.animation.AnimationUtils
import android.widget.Toast
import androidx.fragment.app.DialogFragment
import com.aliyun.facebody20191230.Client
import com.aliyun.facebody20191230.models.SearchFaceAdvanceRequest
import com.aliyun.facebody20191230.models.SearchFaceResponse
import com.aliyun.tea.TeaException
import com.aliyun.tea.TeaModel
import com.aliyun.teaopenapi.models.Config
import com.aliyun.teautil.Common
import com.aliyun.teautil.models.RuntimeOptions
import com.blankj.utilcode.util.ThreadUtils.runOnUiThread
import com.blankj.utilcode.util.ToastUtils
import com.google.gson.GsonBuilder
import com.google.gson.JsonSyntaxException
import com.xcexample.electronicclasscard.GlideHelper
import com.xcexample.electronicclasscard.R
import com.xcexample.electronicclasscard.databinding.LayoutDoorBinding
import com.xcexample.electronicclasscard.kaoqin.ClockBean
import com.xcexample.electronicclasscard.kaoqin.StuInfoBean
import com.xcexample.electronicclasscard.log.LogUtils
import com.xcexample.electronicclasscard.net.ApiFactory
import com.xcexample.electronicclasscard.net.BaseURL
import com.ys.rkapi.MyManager
import okhttp3.ResponseBody
import org.json.JSONException
import org.json.JSONObject
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.io.*
import java.text.SimpleDateFormat
import java.util.*


class DoorFragment(
    var accessKeyId: String,
    var accessKeySecret: String,
    var securityToken: String,
    var close: () -> Unit
) : DialogFragment() {

    private var _binding: LayoutDoorBinding? = null
    private val TAG = "DoorFragment"

    private val binding get() = _binding!!
    private var client: Client? = null
    var camera: Camera? = null
    var manager: MyManager? = null
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
    ): View {
        _binding = LayoutDoorBinding.inflate(inflater, container, false)
        return binding.root

    }

    fun hasCamera(context: Context): Boolean {
        val pm: PackageManager = context.getPackageManager()
        return pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        this.dialog?.setCanceledOnTouchOutside(false)
        manager = MyManager.getInstance(context)
        binding.ivClose.setOnClickListener {
            dismiss()
        }

        val hasCamera = hasCamera(context!!)
        if (!hasCamera) {
            ToastUtils.showShort("没有摄像头")
            dismiss()
        }
        try {
            val config = Config()
                .setAccessKeyId(accessKeyId)
                .setAccessKeySecret(accessKeySecret)
                .setSecurityToken(securityToken)
            config.endpoint = "facebody.cn-shanghai.aliyuncs.com"
            client = Client(config)
        } catch (e: java.lang.Exception) {
            Log.e(TAG, String.format("onCreate: %s", e.message))
            showToastMsg("初始化失败")
        }
        try {
            camera = Camera.open()
        } catch (e: Exception) {

        }
        binding.surfaceView.holder.addCallback(object : SurfaceHolder.Callback {
            override fun surfaceCreated(holder: SurfaceHolder) {
                openFrontCamera()
                Handler().postDelayed({
                    runOnUiThread {
                        binding.progress.startAnimation(
                            AnimationUtils.loadAnimation(
                                context,
                                R.anim.pull_pro_anim
                            )
                        )
                    }
                    camera?.takePicture(null, null) { data, camera ->
                        binding.loading.visibility = View.VISIBLE
                        try {
                            Thread {
                                try {
                                    val inputStream: InputStream = ByteArrayInputStream(data)
                                    val req =
                                        SearchFaceAdvanceRequest().setLimit(1).setDbName("banpai")
                                            .setImageUrlObject(inputStream)
                                    val runtime = RuntimeOptions()
                                    val resp: SearchFaceResponse =
                                        client!!.searchFaceAdvance(req, runtime)

                                    Log.e(
                                        TAG, String.format(
                                            "%s", Common.toJSONString(TeaModel.buildMap(resp))
                                        )
                                    )
                                    if (resp.statusCode == 200) {
                                        var first =
                                            resp.body.data.matchList.first().getFaceItems().first()
                                        var entityId =
                                            first
                                                .getEntityId()
                                        runOnUiThread {
                                            if (first.score >= 0.6) {
                                                binding.stuInfo.visibility = View.VISIBLE
                                                binding.loading.visibility = View.GONE
                                                binding.checkResult.visibility = View.VISIBLE
                                                var extra = first.extraData ?: ""
                                                if (extra.isEmpty()) {
                                                    extra = "student"
                                                }
                                                try {
                                                    Thread {
                                                        manager?.gpio1 = "1"
                                                    }.start()
                                                    ToastUtils.showShort("开锁成功")
                                                } catch (e: Exception) {
                                                    ToastUtils.showShort("开锁失败")
                                                }
                                                clock(entityId, extra)
                                                stuInfo(entityId, extra)
                                            } else {
                                                binding.loading.visibility = View.GONE
                                                binding.error.visibility = View.VISIBLE
                                                binding.ivClose.visibility = View.VISIBLE
                                                ToastUtils.showShort("识别失败，请重试")
                                            }

                                        }

                                    } else {
                                        binding.loading.visibility = View.GONE
                                        binding.error.visibility = View.VISIBLE
                                        binding.ivClose.visibility = View.VISIBLE
                                        ToastUtils.showShort("识别失败，请重试")
                                    }
                                } catch (teaException: TeaException) {
                                    LogUtils.e("teaException " + teaException.message)
                                    runOnUiThread {
                                        binding.loading.visibility = View.GONE
                                        binding.error.visibility = View.VISIBLE
                                        binding.ivClose.visibility = View.VISIBLE
                                        ToastUtils.showShort("识别失败，请重试")
                                    }

                                } catch (e: FileNotFoundException) {
                                    runOnUiThread {
                                        binding.loading.visibility = View.GONE
                                        binding.error.visibility = View.VISIBLE
                                        binding.ivClose.visibility = View.VISIBLE
                                    }


                                } catch (e: Exception) {
                                    LogUtils.e("${e.message}")
                                    runOnUiThread {
                                        binding.loading.visibility = View.GONE
                                        binding.error.visibility = View.VISIBLE
                                        binding.ivClose.visibility = View.VISIBLE
                                    }
                                }
                            }.start()

                        } catch (e: Exception) {

                        }

                    }
                }, 5000)
            }

            override fun surfaceChanged(
                holder: SurfaceHolder,
                format: Int,
                width: Int,
                height: Int
            ) {

            }

            override fun surfaceDestroyed(holder: SurfaceHolder) {
                if (camera != null) {
                    camera?.stopPreview();
                    camera?.release();
                }
            }

        })

    }

    private fun clock(stuid: String, extraData: String) {
        var retrofit = ApiFactory.create(BaseURL, true)
        var call = retrofit.clock(stuid, extraData)
        call.enqueue(object : Callback<ResponseBody?> {
            override fun onResponse(
                call: Call<ResponseBody?>,
                response: Response<ResponseBody?>
            ) {
                val json = response.body()?.string()
                if (!json.isNullOrEmpty()) {
                    try {
                        val gson = GsonBuilder().create()
                        val obj = gson.fromJson(json, ClockBean::class.java)
                        LogUtils.e("result:$obj")
                        if (obj.code == 0) {
                            ToastUtils.showShort("打卡成功")
                        } else {
                            Toast.makeText(this@DoorFragment.context, obj.msg, Toast.LENGTH_SHORT)
                                .show()
                        }

                    } catch (e: JSONException) {
                        e.printStackTrace()
                    }
                }


            }

            override fun onFailure(call: Call<ResponseBody?>, t: Throwable) {

            }
        })

    }

    private fun stuInfo(stuid: String, extraData: String) {
        var retrofit = ApiFactory.create(BaseURL, true)
        var call = retrofit.stuInfo(stuid, null)
        call.enqueue(object : Callback<ResponseBody?> {
            override fun onResponse(
                call: Call<ResponseBody?>,
                response: Response<ResponseBody?>
            ) {
                val json = response.body()?.string()
                LogUtils.e("学生人脸信息：" + json)
                if (!json.isNullOrEmpty()) {
                    val gson = GsonBuilder().create()
                    try {
                        val obj = gson.fromJson(json, StuInfoBean::class.java)
                        LogUtils.e("result:$obj")
                        if (obj.code == 0) {
                            runOnUiThread {
                                if (extraData == "teacher") {
                                    binding.tvInfo.text =
                                        "手机号：${obj.data.card_no}    姓名：${obj.data.name}"
                                } else {
                                    binding.tvInfo.text =
                                        "学号：${obj.data.card_no}    姓名：${obj.data.name}    班级：${obj.data.class_name}"
                                }

                                GlideHelper.loadCircleImage(
                                    this@DoorFragment.context,
                                    binding.avatar,
                                    obj.data.avatar,
                                    R.mipmap.default_class
                                )
                                binding.linInfo.visibility = View.VISIBLE

                                Handler().postDelayed({
                                    dismiss()
                                }, 5000)
                            }

                        } else {
                            Toast.makeText(this@DoorFragment.context, obj.msg, Toast.LENGTH_SHORT)
                                .show()
                        }
                    } catch (e: JSONException) {
                        LogUtils.e("JSONException：" + e)
                    } catch (e: JsonSyntaxException) {
                        LogUtils.e("JsonSyntaxException：" + e)
                    }
                }


            }

            override fun onFailure(call: Call<ResponseBody?>, t: Throwable) {

            }
        })

    }

    override fun dismiss() {
        close()
        super.dismiss()

    }

    /**
     * 显示toast
     *
     * @param msg 内容
     */
    private fun showToastMsg(msg: String) {
        if (TextUtils.isEmpty(msg)) {
            return
        }
        if (Looper.getMainLooper() == Looper.myLooper()) {
            Toast.makeText(this@DoorFragment.context, msg, Toast.LENGTH_SHORT).show()
        } else {
            runOnUiThread(Runnable {
                Toast.makeText(this@DoorFragment.context, msg, Toast.LENGTH_SHORT).show()
            })
        }
    }

    private fun getOutputMediaFile(): File? {
        val mediaStorageDir = File(
            Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES
            ), "MyApp"
        )
        if (!mediaStorageDir.exists()) {
            if (!mediaStorageDir.mkdirs()) {
                return null
            }
        }
        val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
        return File(
            mediaStorageDir.path + File.separator + "IMG_" + timeStamp + ".jpg"
        )
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }


    override fun onStart() {
        super.onStart()
        val displayMetrics = DisplayMetrics()
        activity?.windowManager?.defaultDisplay?.getMetrics(displayMetrics)
        val width = displayMetrics.widthPixels * 0.5
        val height = displayMetrics.heightPixels * 0.8
        dialog?.window?.setLayout(width.toInt(), height.toInt())
    }

    private fun openFrontCamera() {
        val cameraId = findFrontCameraId()
        if (cameraId != -1) {
            try {
                camera = Camera.open(cameraId)
                camera?.setPreviewDisplay(binding.surfaceView.getHolder())
                camera?.startPreview()
            } catch (e: IOException) {
                ToastUtils.showShort("初始化摄像头失败")
            }
        } else {
            ToastUtils.showShort("初始化摄像头失败")
        }
    }

    private fun findFrontCameraId(): Int {
        val cameraInfo = Camera.CameraInfo()
        val numberOfCameras = Camera.getNumberOfCameras()
        for (i in 0 until numberOfCameras) {
            Camera.getCameraInfo(i, cameraInfo)
//            if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
//                return i
//            }
            return i
        }
        return -1
    }
}